package com.prisetree.isv.response.vo;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.springframework.asm.Type;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InterfaceMaker;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.alibaba.fastjson.serializer.PropertyFilter;
import com.prisetree.isv.common.annotation.SysDict;
import com.prisetree.isv.service.SysDictService;


public class ResponseVOFactory {
	
	private static SysDictService sysDictService = new SysDictService();
	private static final String METHOD_POST_NAME = "StrLabel";
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T> T getInstance(Class<T> clazz)
	{
		T t = null;
		Method[] methods = clazz.getDeclaredMethods();
		if(methods != null)
		{
			final List<CglibMethod> ml = new ArrayList<CglibMethod>();
			for(Method method : methods)
			{
				SysDict sa = method.getAnnotation(SysDict.class);
				if(sa != null)
				{
					ml.add(new CglibMethod(method, sa.value()));
				}
			}
			if(ml.size() > 0)
			{
				InterfaceMaker im = new InterfaceMaker();
				for(CglibMethod method : ml)
				{
					im.add(new Signature(method.getMethod().getName() + METHOD_POST_NAME, Type.getType(String.class), new Type[] {}),  null);  
				}
		  
				Class myInterface = im.create();
		        Enhancer enhancer = new Enhancer();  
		        enhancer.setSuperclass(clazz);
		        enhancer.setInterfaces(new Class[] { myInterface });  
		        enhancer.setCallback(new MethodInterceptor() {  
		        	
		        	private List<CglibMethod> cgml = ml;
					@Override
					public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		                if (method.getName().endsWith(METHOD_POST_NAME)) 
		                {  
		                	String originMethodName = method.getName().substring(0, method.getName().length() - METHOD_POST_NAME.length());
		                	for(CglibMethod m : cgml)
		                	{
		                		Method originMethod = m.getMethod();
		                		if(originMethod.getName().equals(originMethodName))
		                		{
		                			return sysDictService.getLabelByTypeValue(m.getLabelType(), originMethod.invoke(obj, args).toString());
		                		}
		                	}
		                }  
		                return proxy.invokeSuper(obj, args);  
					}  
		        });
		        t = (T) enhancer.create();
			}
		}
		if(t == null)
		{
			try {
				t = clazz.newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return t;
	}
	
	private static class CglibMethod{
		private Method method;
		private String labelType;
		public CglibMethod(Method method, String labelType)
		{
			this.method = method;
			this.labelType = labelType;
		}
		public Method getMethod() {
			return method;
		}
		public String getLabelType() {
			return labelType;
		}
	}
	
	
	public static void main(String[] args)
	{
		CreateObjectResponse res = ResponseVOFactory.getInstance(CreateObjectResponse.class);
		PropertyFilter profilter = new PropertyFilter(){  
            @Override  
            public boolean apply(Object object, String name, Object value) {  
                if(name.equalsIgnoreCase("callbacks")){  
                    return false;  
                }  
                return true;  
            }  
        };
//		System.out.println(JSON.toJSONString(JSON.toJSON(res), profilter));
	}
}
